From d22746ede91f366b9bb2582bd85e3e473308d11e Mon Sep 17 00:00:00 2001 From: "shand@ubuntu.eng.hq.xensource.com" Date: Tue, 30 Aug 2005 11:28:26 -0800 Subject: [PATCH] Provide xend support for setting up TPM front- and back-end interfaces. Signed-off-by: Steven Hand Signed-off-by: Stefan Berger --- tools/examples/xmexample1 | 14 ++++ tools/examples/xmexample2 | 14 ++++ tools/examples/xmexample3 | 14 ++++ tools/python/xen/xend/XendDomainInfo.py | 37 ++++++++++ tools/python/xen/xend/image.py | 9 +++ tools/python/xen/xend/server/tpmif.py | 52 +++++++++++++++ tools/python/xen/xm/create.py | 89 +++++++++++++++++++++++++ 7 files changed, 229 insertions(+) create mode 100644 tools/python/xen/xend/server/tpmif.py diff --git a/tools/examples/xmexample1 b/tools/examples/xmexample1 index a5cf683c5b..b3aecf854e 100644 --- a/tools/examples/xmexample1 +++ b/tools/examples/xmexample1 @@ -47,6 +47,20 @@ name = "ExampleDomain" disk = [ 'phy:hda1,hda1,w' ] +#---------------------------------------------------------------------------- +# Define to which TPM instance the user domain should communicate. +# The vtpm entry is of the form 'instance=INSTANCE,backend=DOM' +# where INSTANCE indicates the instance number of the TPM the VM +# should be talking to and DOM provides the domain where the backend +# is located. +# Note that no two virtual machines should try to connect to the same +# TPM instance. The handling of all TPM instances does require +# some management effort in so far that VM configration files (and thus +# a VM) should be associated with a TPM instance throughout the lifetime +# of the VM / VM configuration file. The instance number must be +# greater or equal to 1. +#vtpm = [ 'instance=1,backend=0' ] + #---------------------------------------------------------------------------- # Set the kernel command line for the new domain. # You only need to define the IP parameters and hostname if the domain's diff --git a/tools/examples/xmexample2 b/tools/examples/xmexample2 index ea349cfa67..0acf32bbec 100644 --- a/tools/examples/xmexample2 +++ b/tools/examples/xmexample2 @@ -83,6 +83,20 @@ vcpus = 4 # make your domain a 4-way disk = [ 'phy:sda%d,sda1,w' % (7+vmid), 'phy:sda6,sda6,r' ] +#---------------------------------------------------------------------------- +# Define to which TPM instance the user domain should communicate. +# The vtpm entry is of the form 'instance=INSTANCE,backend=DOM' +# where INSTANCE indicates the instance number of the TPM the VM +# should be talking to and DOM provides the domain where the backend +# is located. +# Note that no two virtual machines should try to connect to the same +# TPM instance. The handling of all TPM instances does require +# some management effort in so far that VM configration files (and thus +# a VM) should be associated with a TPM instance throughout the lifetime +# of the VM / VM configuration file. The instance number must be +# greater or equal to 1. +#vtpm = ['instance=%d,backend=0' % (vmid) ] + #---------------------------------------------------------------------------- # Set the kernel command line for the new domain. # You only need to define the IP parameters and hostname if the domain's diff --git a/tools/examples/xmexample3 b/tools/examples/xmexample3 index fd96a7b201..1fa80cb2e3 100644 --- a/tools/examples/xmexample3 +++ b/tools/examples/xmexample3 @@ -79,6 +79,20 @@ vif = [ 'ip=192.168.%d.1/24' % (vmid)] # All domains get sda6 read-only (to use for /usr, see below). disk = [ 'phy:hda%d,hda1,w' % (vmid)] +#---------------------------------------------------------------------------- +# Define to which TPM instance the user domain should communicate. +# The vtpm entry is of the form 'instance=INSTANCE,backend=DOM' +# where INSTANCE indicates the instance number of the TPM the VM +# should be talking to and DOM provides the domain where the backend +# is located. +# Note that no two virtual machines should try to connect to the same +# TPM instance. The handling of all TPM instances does require +# some management effort in so far that VM configration files (and thus +# a VM) should be associated with a TPM instance throughout the lifetime +# of the VM / VM configuration file. The instance number must be +# greater or equal to 1. +#vtpm = ['instance=%d,backend=0' % (vmid) ] + #---------------------------------------------------------------------------- # Set the kernel command line for the new domain. # You only need to define the IP parameters and hostname if the domain's diff --git a/tools/python/xen/xend/XendDomainInfo.py b/tools/python/xen/xend/XendDomainInfo.py index 7ee3930fd8..be1e630cdb 100644 --- a/tools/python/xen/xend/XendDomainInfo.py +++ b/tools/python/xen/xend/XendDomainInfo.py @@ -269,6 +269,7 @@ class XendDomainInfo: self.blkif_backend = False self.netif_backend = False self.netif_idx = 0 + self.tpmif_backend = False #todo: state: running, suspended self.state = STATE_VM_OK @@ -458,6 +459,31 @@ class XendDomainInfo: return + if type == 'vtpm': + backdom = domain_exists(sxp.child_value(devconfig, 'backend', '0')) + + devnum = int(sxp.child_value(devconfig, 'instance', '0')) + log.error("The domain has a TPM with instance %d." % devnum) + + # create backend db + backdb = backdom.db.addChild("/backend/%s/%s/%d" % + (type, self.uuid, devnum)) + # create frontend db + db = self.db.addChild("/device/%s/%d" % (type, devnum)) + + backdb['frontend'] = db.getPath() + backdb['frontend-id'] = "%i" % self.id + backdb['instance'] = sxp.child_value(devconfig, 'instance', '0') + backdb.saveDB(save=True) + + db['handle'] = "%i" % devnum + db['backend'] = backdb.getPath() + db['backend-id'] = "%i" % int(sxp.child_value(devconfig, + 'backend', '0')) + db.saveDB(save=True) + + return + ctrl = self.findDeviceController(type) return ctrl.createDevice(devconfig, recreate=self.recreate, change=change) @@ -779,6 +805,11 @@ class XendDomainInfo: for dev in typedb.keys(): typedb[dev].delete() typedb.saveDB(save=True) + if type == 'vtpm': + typedb = ddb.addChild(type) + for dev in typedb.keys(): + typedb[dev].delete() + typedb.saveDB(save=True) def show(self): """Print virtual machine info. @@ -1018,6 +1049,8 @@ class XendDomainInfo: self.netif_backend = True elif name == 'usbif': self.usbif_backend = True + elif name == 'tpmif': + self.tpmif_backend = True else: raise VmError('invalid backend type:' + str(name)) @@ -1190,6 +1223,10 @@ from server import netif controller.addDevControllerClass("vif", netif.NetifController) add_device_handler("vif", "vif") +from server import tpmif +controller.addDevControllerClass("vtpm", tpmif.TPMifController) +add_device_handler("vtpm", "vtpm") + from server import pciif controller.addDevControllerClass("pci", pciif.PciController) add_device_handler("pci", "pci") diff --git a/tools/python/xen/xend/image.py b/tools/python/xen/xend/image.py index 8e9f5fa0a6..09b6b9fc47 100644 --- a/tools/python/xen/xend/image.py +++ b/tools/python/xen/xend/image.py @@ -32,6 +32,9 @@ SIF_BLK_BE_DOMAIN = (1<<4) """Flag for a net device backend domain.""" SIF_NET_BE_DOMAIN = (1<<5) +"""Flag for a TPM device backend domain.""" +SIF_TPM_BE_DOMAIN = (1<<7) + class ImageHandler: """Abstract base class for image handlers. @@ -194,6 +197,7 @@ class ImageHandler: self.flags = 0 if self.vm.netif_backend: self.flags |= SIF_NET_BE_DOMAIN if self.vm.blkif_backend: self.flags |= SIF_BLK_BE_DOMAIN + if self.vm.tpmif_backend: self.flags |= SIF_TPM_BE_DOMAIN if self.vm.recreate or self.vm.restore: return @@ -366,6 +370,11 @@ class VmxImageHandler(ImageHandler): mac = sxp.child_value(vifinfo, 'mac') ret.append("-macaddr") ret.append("%s" % mac) + if name == 'vtpm': + vtpminfo = sxp.child(device, 'vtpm') + instance = sxp.child_value(vtpminfo, 'instance') + ret.append("-instance") + ret.append("%s" % instance) # Handle graphics library related options vnc = sxp.child_value(self.vm.config, 'vnc') diff --git a/tools/python/xen/xend/server/tpmif.py b/tools/python/xen/xend/server/tpmif.py new file mode 100644 index 0000000000..59e4202c86 --- /dev/null +++ b/tools/python/xen/xend/server/tpmif.py @@ -0,0 +1,52 @@ +# Copyright (C) 2005 IBM Corporation +# Authort: Stefan Berger, stefanb@us.ibm.com +# Derived from netif.py: +# Copyright (C) 2004 Mike Wray +"""Support for virtual TPM interfaces. +""" + +import random + +from xen.xend import sxp +from xen.xend.XendError import XendError, VmError +from xen.xend.XendLogging import log +from xen.xend.XendRoot import get_component +from xen.xend.xenstore import DBVar + +from xen.xend.server import channel +from xen.xend.server.controller import CtrlMsgRcvr, Dev, DevController +from xen.xend.server.messages import * + +class TPMifController(DevController): + """TPM interface controller. Handles all TPM devices for a domain. + """ + + def __init__(self, vm, recreate=False): + DevController.__init__(self, vm, recreate=recreate) + self.rcvr = None + self.channel = None + + def initController(self, recreate=False, reboot=False): + self.destroyed = False + self.channel = self.getChannel() + + def destroyController(self, reboot=False): + """Destroy the controller and all devices. + """ + self.destroyed = True + self.destroyDevices(reboot=reboot) + if self.rcvr: + self.rcvr.deregisterChannel() + + def sxpr(self): + val = ['tpmif', ['dom', self.getDomain()]] + return val + + def newDevice(self, id, config, recreate=False): + """Create a TPM device. + + @param id: interface id + @param config: device configuration + @param recreate: recreate flag (true after xend restart) + """ + return None diff --git a/tools/python/xen/xm/create.py b/tools/python/xen/xm/create.py index ec4ab49c12..dbf1dd116c 100644 --- a/tools/python/xen/xm/create.py +++ b/tools/python/xen/xm/create.py @@ -175,6 +175,12 @@ gopts.var('netif', val='no|yes', fn=set_bool, default=0, use="Make the domain a network interface backend.") +gopts.var('tpmif', val='frontend=DOM', + fn=append_value, default=[], + use="""Make the domain a TPM interface backend. If frontend is given, + the frontend in that domain is connected to this backend (not + completely implemented, yet)""") + gopts.var('disk', val='phy:DEV,VDEV,MODE[,DOM]', fn=append_value, default=[], use="""Add a disk device to a domain. The physical device is DEV, @@ -213,6 +219,12 @@ gopts.var('vif', val="mac=MAC,be_mac=MAC,bridge=BRIDGE,script=SCRIPT,backend=DOM This option may be repeated to add more than one vif. Specifying vifs will increase the number of interfaces as needed.""") +gopts.var('vtpm', val="instance=INSTANCE,backend=DOM", + fn=append_value, default=[], + use="""Add a tpm interface. On the backend side us the the given + instance as virtual TPM instance. Use the backend in the given + domain.""") + gopts.var('nics', val="NUM", fn=set_int, default=1, use="""Set the number of network interfaces. @@ -369,6 +381,46 @@ def configure_usb(opts, config_devs, vals): config_usb = ['usb', ['path', path]] config_devs.append(['device', config_usb]) +def configure_vtpm(opts, config_devs, vals): + """Create the config for virtual TPM interfaces. + """ + vtpm = vals.vtpm + vtpm_n = 1 + for idx in range(0, vtpm_n): + if idx < len(vtpm): + d = vtpm[idx] + instance = d.get('instance') + if instance == "VTPMD": + instance = "0" + else: + try: + if int(instance) == 0: + opts.err('VM config error: vTPM instance must not be 0.') + except ValueError: + opts.err('Vm config error: could not parse instance number.') + backend = d.get('backend') + config_vtpm = ['vtpm'] + if instance: + config_vtpm.append(['instance', instance]) + if backend: + config_vtpm.append(['backend', backend]) + config_devs.append(['device', config_vtpm]) + +def configure_tpmif(opts, config_devs, vals): + """Create the config for virtual TPM interfaces. + """ + tpmif = vals.tpmif + tpmif_n = 1 + for idx in range(0, tpmif_n): + if idx < len(tpmif): + d = tpmif[idx] + frontend = d.get('frontend') + config_tpmif = ['tpmif'] + if frontend: + config_tpmif.append(['frontend', frontend]) + config_devs.append(['device', config_tpmif]) + + def randomMAC(): """Generate a random MAC address. @@ -479,6 +531,8 @@ def make_config(opts, vals): config.append(['backend', ['blkif']]) if vals.netif: config.append(['backend', ['netif']]) + if vals.tpmif: + config.append(['backend', ['tpmif']]) if vals.restart: config.append(['restart', vals.restart]) @@ -491,6 +545,7 @@ def make_config(opts, vals): configure_pci(opts, config_devs, vals) configure_vifs(opts, config_devs, vals) configure_usb(opts, config_devs, vals) + configure_vtpm(opts, config_devs, vals) configure_vmx(opts, config_devs, vals) config += config_devs @@ -539,6 +594,38 @@ def preprocess_vifs(opts, vals): vifs.append(d) vals.vif = vifs +def preprocess_vtpm(opts, vals): + if not vals.vtpm: return + vtpms = [] + for vtpm in vals.vtpm: + d = {} + a = vtpm.split(',') + for b in a: + (k, v) = b.strip().split('=', 1) + k = k.strip() + v = v.strip() + if k not in ['backend', 'instance']: + opts.err('Invalid vtpm specifier: ' + vtpm) + d[k] = v + vtpms.append(d) + vals.vtpm = vtpms + +def preprocess_tpmif(opts, vals): + if not vals.tpmif: return + tpmifs = [] + for tpmif in vals.tpmif: + d = {} + a = tpmif.split(',') + for b in a: + (k, v) = b.strip().split('=', 1) + k = k.strip() + v = v.strip() + if k not in ['frontend']: + opts.err('Invalid tpmif specifier: ' + vtpm) + d[k] = v + tpmifs.append(d) + vals.tpmif = tpmifs + def preprocess_ip(opts, vals): if vals.ip or vals.dhcp != 'off': dummy_nfs_server = '1.2.3.4' @@ -627,6 +714,8 @@ def preprocess(opts, vals): preprocess_ip(opts, vals) preprocess_nfs(opts, vals) preprocess_vnc(opts, vals) + preprocess_vtpm(opts, vals) + preprocess_tpmif(opts, vals) def make_domain(opts, config): """Create, build and start a domain. -- 2.30.2